﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MyEngineExercise.我的扩展.自定义接口;
using System.Runtime.InteropServices;
using MyEngineExercise.我的扩展.自定义事件参数类;
using System.Drawing;
using System.Windows.Forms;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;
using MyEngineExercise.我的扩展.枚举;
using ESRI.ArcGIS.SystemUI;
using System.Diagnostics;
using System.Reflection;

namespace MyEngineExercise.我的扩展.绘制多边形
{
    /// <summary>
    /// 绘制矩形工具
    /// </summary>
    public class EnvelopeFeedbackTool : IGeometryComplete,ITool,ICommand
    {
        [DllImport("gdi32.dll")]
        static extern bool DeleteObject(IntPtr hObject);


        /// <summary>
        /// 事件：几何图形绘制完成后发生
        /// </summary>
        public event EventHandler<GeometryCompleteArgs> GeometryComplete = null;


        private Bitmap _bitmap = null;//工具栏图标
        private IntPtr _hBitmap = IntPtr.Zero;
        private Cursor _crossCursor = null;
        private Cursor _panCursor = null;

        private IHookHelper _hookHelper = null;
        private IHookActions _hookActions = null;

        private INewEnvelopeFeedback _newEnvelopeFeedback = null;
        //private INewEnvelopeFeedback2 _newEnvelopeFeedback = null;
        /// <summary>
        /// 记录第一次点击左键的点坐标
        /// </summary>
        IPoint _point = null;

        private Boolean _isMouseDown = false;//记录是否有点击鼠标左键
        private Boolean _isPanUsed = false;//是否在使用pan

        /// <summary>
        /// 记录当前ScreenDisplay实例,用于pan操作
        /// </summary>
        private IScreenDisplay _focusScreenDisplay = null;

        private const Int32 CLICK_LEFT_MOUSE = 1;
        private const Int32 RIGHT_MOUSE = 2;
        private const Int32 CLICK_MIDDLE_MOUSE = 4;
        private const Int32 NONE_MOUSE = 0;

        /// <summary>
        /// 动态矩形，onMouseMove.用来计算面积
        /// </summary>
        private readonly IEnvelope _dynamicEnvelop = new EnvelopeClass();


        /// <summary>
        /// 用于主窗口状态栏显示面积
        /// </summary>
        private ToolStripStatusLabel _toolStripStatusLabel = null;


        /// <summary>
        /// 构造函数
        /// </summary>
        public EnvelopeFeedbackTool(ToolStripStatusLabel toolStripStatusLabel)
        {
            _toolStripStatusLabel = toolStripStatusLabel;

            _dynamicEnvelop = new EnvelopeClass();

            _hookHelper = new HookHelperClass();

            _crossCursor = CursorStyle.GetCursor(Constants.CROSS_CURSOR_FILENAME);
            _panCursor = CursorStyle.GetCursor(Constants.MOVEHAND_CURSOR_FILENAME);


            if (_crossCursor == null)
                MessageBox.Show("cross cursor is null");
            if (_panCursor == null)
                MessageBox.Show("pan cursor is null");

            _bitmap = MyEngineExercise.Properties.Resources.drawEnvelopeIcon;
            _hBitmap = _bitmap.GetHbitmap();

        }


        /// <summary>
        /// 析构函数
        /// </summary>
        ~EnvelopeFeedbackTool()
        {
            if (_hBitmap.ToInt32() != 0)
                DeleteObject(_hBitmap);

            _hookHelper = null;
            _crossCursor = null;
            _panCursor = null;
        }


        #region 实现ICommand
        public int Bitmap { get { return _hBitmap.ToInt32(); } }

        public string Caption { get { return "Caption"; } }

        public string Category { get { return "GiftGis_FeedBackTools"; } }

        public bool Checked { get { return false; } }

        //public bool Enabled { get { return _hookHelper.ActiveView is Map; } }
        public bool Enabled { get { return true; } }

        public int HelpContextID { get { return 0; } }

        public string HelpFile { get { return null; } }

        public string Message { get { return "按住鼠标左键框选一个范围"; } }

        public string Name { get { return "Name"; } }

        public string Tooltip { get { return "画矩形"; } }

        public void OnClick()
        {
            //if (null != _newEnvelopeFeedback)
            //    _newEnvelopeFeedback.Refresh(_hookHelper.ActiveView.ScreenDisplay.hDC);
        }

        public void OnCreate(object hook)
        {
            _hookHelper.Hook = hook;
            _hookActions = (IHookActions)_hookHelper;

        }
        #endregion



        #region 实现ITool
        public int Cursor { get { return (_isPanUsed ? _panCursor : _crossCursor).Handle.ToInt32(); } }

        public bool Deactivate() { return true; }

        public bool OnContextMenu(int x, int y) { return false; }

        public void OnDblClick(){}

        public void OnKeyDown(int keyCode, int shift)
        {
            if (_isMouseDown && keyCode == 27) // ESC
            {
                _isMouseDown = false;
                _newEnvelopeFeedback = null;
                _hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
            }
        }

        public void OnKeyUp(int keyCode, int shift) { }


        public void OnMouseDown(int button, int shift, int x, int y)
        {
            //测试这2个引用是否相等
            //if (Object.ReferenceEquals(_hookHelper.FocusMap, _hookHelper.ActiveView.FocusMap))
                //MessageBox.Show("_hookHelper.FocusMap和_hookHelper.ActiveView.FocusMap引用同一对象");

  
            //Debug.Print("OnMouseDown");


            IActiveView activeView = _hookHelper.ActiveView;

            if (null == activeView)
                return;


            //如果活动视图是page，设置page的focusmap是点所在map
            //If the active view is a page layout
            if (activeView is IPageLayout)
            {
                //Create a point in map coordinates
                IPoint point = (IPoint)activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
                //Get the map if the point is within a data frame
                IMap map = activeView.HitTestMap(point);
                if (null == map)
                    return;

                //Set the map to be the page layout's focus map
                if (_hookHelper.FocusMap != map)
                {
                    activeView.FocusMap = map;
                    activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
                }
            }


            //Create a point in map coordinates
            activeView = (IActiveView)_hookHelper.FocusMap;
            _point = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);

            if (button == CLICK_MIDDLE_MOUSE)
            {
                _isPanUsed = true;//pan操作
                _focusScreenDisplay = getFocusScreenDisplay();//如果是pan操作，记录当前screenDisplay
                //Start the pan operation 
                _focusScreenDisplay.PanStart(_point);
            }

            if (button == CLICK_LEFT_MOUSE)// 只设置 m_IsMouseDown 为true,具体的画矩形操作在OnMouseMove事件中
            {
                _isMouseDown = true;
            }
        }


        public void OnMouseMove(int button, int shift, int x, int y)
        {
            if (button == CLICK_MIDDLE_MOUSE && _isPanUsed)//pan操作
            {
                IPoint point = _focusScreenDisplay.DisplayTransformation.ToMapPoint(x, y);
                _focusScreenDisplay.PanMoveTo(point);
            }

            if (_isMouseDown)//画矩形操作
            {
                //Get the focus map
                IActiveView activeView = (IActiveView)_hookHelper.FocusMap;
                //移动到的点
                IPoint point = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(x, y);

                //Start an envelope feedback
                //开始绘制矩形
                if (null == _newEnvelopeFeedback)
                {
                    _newEnvelopeFeedback = new NewEnvelopeFeedbackClass();
                    _newEnvelopeFeedback.Display = activeView.ScreenDisplay;
                    _newEnvelopeFeedback.Start(point);//开始绘制矩形
                }
                else//动态显示面积
                {
                    double xMin = Math.Min(_point.X, point.X);
                    double xMax = Math.Max(_point.X, point.X);
                    double yMin = Math.Min(_point.Y, point.Y);
                    double yMax = Math.Max(_point.Y, point.Y);
                    _dynamicEnvelop.PutCoords(xMin, yMin, xMax, yMax);//生成矩形
                    IArea pArea = (IArea)_dynamicEnvelop;
                    Double area=pArea.Area;
                    //Debug.Print(area.ToString());
                    _toolStripStatusLabel.Text = (null != pArea) ? String.Format("{0:F03}平方米", area) : "no area";
                }

                _newEnvelopeFeedback.MoveTo(point);
            }
        }


        public void OnMouseUp(int button, int shift, int x, int y)
        {
            if (button == CLICK_MIDDLE_MOUSE && _isPanUsed)//pan操作
            {
                IEnvelope panEnvelope = _focusScreenDisplay.PanStop();//停止
                //Check if user dragged a rectangle or just clicked.
                //If a rectangle was dragged, m_ipFeedback in non-NULL
                if (null != panEnvelope)
                {
                    _focusScreenDisplay.DisplayTransformation.VisibleBounds = panEnvelope;
                    //使作废,释放资源
                    _focusScreenDisplay.Invalidate(null, true, (short)esriScreenCache.esriAllScreenCaches);
                }
                _isPanUsed = false;//完成了一次pan操作
            }

            if (_isMouseDown)//画矩形操作
            {
                //Get the focus map
                IActiveView activeView = (IActiveView)_hookHelper.FocusMap;

                if (null == _newEnvelopeFeedback)
                {
                    _isMouseDown = false;
                    return;
                }

                //Stop the envelope feedback
                //为什么用INewEnvelopeFeedback2接口不行的？而且不会执行下面的语句
                //IEnvelope resultEnvelope = (IEnvelope)_newEnvelopeFeedback.Stop();
                IEnvelope resultEnvelope = _newEnvelopeFeedback.Stop();

                /*if (resultEnvelope.Width == resultEnvelope.XMax - resultEnvelope.XMin)
                    MessageBox.Show("平面长");
                else
                    MessageBox.Show("球面长");


                if ((resultEnvelope.XMax - resultEnvelope.XMin) * (resultEnvelope.YMax - resultEnvelope.YMin) == ((IArea)resultEnvelope).Area)
                    MessageBox.Show("平面面积");
                else
                    MessageBox.Show("球面面积");*/

                
                //MessageBox.Show("程序有执行这里！");

                _newEnvelopeFeedback = null;
                _isMouseDown = false;//完成一次画多边形操作

                if (resultEnvelope.Width != 0 && resultEnvelope.Height != 0 && !resultEnvelope.IsEmpty)
                {
                    _hookActions.DoAction(resultEnvelope, esriHookActions.esriHookActionsFlash);//闪烁
                    if (null != GeometryComplete)//绘制完成后什么都不做
                        GeometryComplete(this, new GeometryCompleteArgs(resultEnvelope));
                }
                else
                    MessageBox.Show("envelope is empty!");
            }
        }


        public void Refresh(int hdc)
        {
            // 注意，必须设置这里，否则，当地图放大缩小后线就会移动。
            if (null != _newEnvelopeFeedback)
                _newEnvelopeFeedback.Refresh(hdc);
        }


        #endregion



        /// <summary>
        /// 获取IScreenDisplay，map和page方法不同
        /// </summary>
        /// <returns></returns>
        private IScreenDisplay getFocusScreenDisplay()
        {
            //Get the ScreenDisplay that has focus
            IActiveView activeView = _hookHelper.ActiveView;

            if (activeView is IMap)
                return activeView.ScreenDisplay;
            else
            {
                activeView = (IActiveView)activeView.FocusMap;
                return activeView.ScreenDisplay;
            }
        }

    }
}
